#ifndef _csPtr_h_
#define _csPtr_h_

/********************************************************************
	created:	2009/11/05
	created:	5:11:2009   14:02
	filename: 	e:\csEngine\csCoreLib\src\common\csPtr.h
	file path:	e:\csEngine\csCoreLib\src\common
	file base:	csPtr
	file ext:	h
	author:		dongchengok
	
	purpose:	smart pointer
*********************************************************************/
#include "../csType.h"

//------------------------------------------------------------------------
template<typename T>
class csPtr
{
public:
	csPtr();
	csPtr(T* obj);
	csPtr(const csPtr<T>& p);
	~csPtr();

	void	operator= (T* obj);
	void	operator= (const csPtr<T>& p);

	bool	operator==(T* obj) const;
	bool	operator==(const csPtr<T>& p) const;

	bool	operator!=(T* obj) const;
	bool	operator!=(const csPtr<T>& p) const;

	T*		operator->() const;
	T&		operator* () const;
	operator T*() const;
	T*		get() const;

	bool	isValid() const;

private:
	T*		m_ptr;
};

//------------------------------------------------------------------------
template<typename T>
csPtr<T>::csPtr()
:m_ptr(csNULL)
{

}

//------------------------------------------------------------------------
template<typename T>
csPtr<T>::csPtr(T* obj)
:m_ptr(obj)
{
	if(csNULL!=m_ptr)
	{
		m_ptr->addReference();
	}
}

//------------------------------------------------------------------------
template<typename T>
csPtr<T>::csPtr(const Ptr<T>& p)
:m_ptr(p.m_ptr)
{
	if(csNULL!=m_ptr)
	{
		m_ptr->addReference();
	}
}

//------------------------------------------------------------------------
template<typename T>
csPtr<T>::~csPtr()
{
	if(csNULL!=m_ptr)
	{
		m_ptr->releaseReference();
		m_ptr = csNULL;
	}
}

//------------------------------------------------------------------------
template<typename T> void
csPtr<T>::operator= (T* obj)
{
	if(m_ptr!=obj)
	{
		if(csNULL!=m_ptr)
		{
			m_ptr->releaseReference();
		}
		m_ptr = obj;
		if(csNULL!=m_ptr)
		{
			m_ptr->addReference();
		}
	}
}

//------------------------------------------------------------------------
template<typename T> void
csPtr<T>::operator= (const Ptr<T>& p)
{
	if(m_ptr!=p.m_ptr)
	{
		if(csNULL!=m_ptr)
		{
			m_ptr->releaseReference();
		}
		m_ptr = p.m_ptr;
		if(csNULL!=m_ptr)
		{
			m_ptr->addReference();
		}
	}
}

//------------------------------------------------------------------------
template<typename T> bool
csPtr<T>::operator==(T* obj) const
{
	return m_ptr==obj;
}

//------------------------------------------------------------------------
template<typename T> bool
csPtr<T>::operator==(const Ptr<T>& p) const
{
	return m_ptr==p.m_ptr;
}

//------------------------------------------------------------------------
template<typename T> bool
csPtr<T>::operator!=(T* obj) const
{
	return m_ptr!=obj;
}

//------------------------------------------------------------------------
template<typename T> bool
csPtr<T>::operator!=(const Ptr<T>& p) const
{
	return m_ptr!=p.m_ptr;
}

//------------------------------------------------------------------------
template<typename T> T*
csPtr<T>::operator->() const
{
	csASSERT(csNULL!=m_ptr);
	return m_ptr;
}

//------------------------------------------------------------------------
template<typename T> T&
csPtr<T>::operator* () const
{
	csASSERT(csNULL!=m_ptr);
	return *m_ptr;
}

//------------------------------------------------------------------------
template<typename T>
csPtr<T>::operator T*() const
{
	return m_ptr;
}

//------------------------------------------------------------------------
template<typename T> T*
csPtr<T>::get() const
{
	return m_ptr;
}

//------------------------------------------------------------------------
template<typename T> bool
csPtr<T>::isValid() const
{
	return m_ptr!=csNULL;
}
#endif // _csPtr_h_

